package com.lz.comm.widget.fragment

import android.os.Bundle
import android.os.Parcelable
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle

/**
 * Created by You on 2020-02-13.
 * 切换时不保存fragment对象引用, 只保存状态Fragment.SaveState, 切换时所有生命方法重新执行
 * 多用于切换模块时重新加载, 保存状态不保存引用
 */
abstract class FragmentStateAdapter(manager: FragmentManager) : FragmentLayout.Adapter(manager) {

    private val mSavedState = ArrayList<Fragment.SavedState?>()

    override fun instantFragment(fm: FragmentLayout, position: Int) {
        val ft = mManager.beginTransaction()
        if (position == mCurrentPosition && mCurrentFragment != null) {
            mCurrentFragment!!.setMenuVisibility(true)
            ft.setMaxLifecycle(mCurrentFragment!!, Lifecycle.State.RESUMED)
            showCurrentFragment(mCurrentFragment!!)
            return
        }

        while (mSavedState.size <= mCurrentPosition) {
            mSavedState.add(null)
        }
        mCurrentFragment?.also {
            it.setMenuVisibility(false)
            ft.setMaxLifecycle(it, Lifecycle.State.STARTED)
            mSavedState[mCurrentPosition] =  mManager.saveFragmentInstanceState(it)
            ft.remove(it)
        }
        val fragment = getItem(position)
        if (mSavedState.size > position) {
            mSavedState[position]?.also { fragment.setInitialSavedState(it) }
        }

        ft.add(fm.id, fragment)
        fragment.setMenuVisibility(true)
        ft.setMaxLifecycle(fragment, Lifecycle.State.RESUMED)
        mCurrentFragment = fragment
        mCurrentPosition = position
        ft.commitNowAllowingStateLoss()
    }

    override fun clearFragments() {
        mCurrentPosition = -1
        val ft = mManager.beginTransaction()
        if (mCurrentFragment != null) {
            ft.remove(mCurrentFragment!!)
            mCurrentFragment = null
        }
        mSavedState.clear()
        ft.commitNowAllowingStateLoss()
    }

    override fun saveState(): Parcelable? {
        var state: Bundle? = null
        if (mSavedState.size > 0) {
            state = Bundle().also {
                val fss = arrayOfNulls<Fragment.SavedState>(mSavedState.size)
                mSavedState.toArray(fss)
                it.putParcelableArray("states", fss)
            }
        }
        if (state == null) {
            state = Bundle()
        }
        state.putInt("currentPosition", mCurrentPosition)
        mCurrentFragment?.also { mManager.putFragment(state, "$KEY$mCurrentPosition", it) }
        return state
    }

    override fun restoreState(state: Parcelable?, loader: ClassLoader?) {
        if (state != null) {
            val bundle = state as Bundle
            bundle.classLoader = loader
            mSavedState.clear()
            bundle.getParcelableArray("states")?.forEach { mSavedState.add(it as Fragment.SavedState) }
            mCurrentPosition = bundle.getInt("currentPosition")
            mCurrentFragment = mManager.getFragment(bundle, "$KEY$mCurrentPosition")
        }
    }

    /**
     * 模块切换时，直接显示已经存在的fragment
     * @param f
     */
    protected open fun showCurrentFragment(f: Fragment) = Unit

    companion object {
        private const val KEY = "FragmentStateAdapter"
    }
}